﻿using Arim.S4.Client.Base;
using Arim.S4.Client.Base.Dto;
using RestSharp;
using System.Collections.Generic;
using System.Configuration;

namespace Arim.S4.Api
{
    public class RestApi<T> where T : class, new()
    {
        public RestApi()
        {
            this.ApiBaseUrl = ConfigurationManager.AppSettings.Get("ApiBaseUrl");
        }

        public RestApi(string baseUrl)
        {
            this.ApiBaseUrl = baseUrl;
        }

        public string ApiBaseUrl { get; set; }

        public T Get(string url, object pars = null)
        {
            var type = Method.GET;
            return ParseDetail(url, pars, type);
        }

        public PagedList<T> GetPagedList(string url, PageDto pager, object pars = null)
        {
            var type = Method.GET;
            return ParsePagedList(url, pager, type, pars);
        }

        public IList<T> GetAll(string url, object pars = null)
        {
            var type = Method.GET;
            var pager = ParsePagedList(url, new PageDto() { Size = 1000 }, type, pars);
            return pager.Items;
        }

        public IList<T> GetList(string url, object pars = null)
        {
            var type = Method.GET;
            return ParseList(url, pars, type);
        }

        public T Post(string url, object pars = null)
        {
            var type = Method.POST;
            return ParseDetail(url, pars, type);
        }

        /// <summary>
        /// 批量更新。
        /// </summary>
        /// <param name="url"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public IList<T> PostMany(string url, IEnumerable<T> items)
        {
            var type = Method.POST;
            return ParseList(url, items, type);
        }

        public void Delete(string url, object pars = null)
        {
            var type = Method.DELETE;
            ParseDetail(url, pars, type);
        }

        public T Put(string url, object pars)
        {
            var type = Method.PUT;
            return ParseDetail(url, pars, type);
        }

        private T ParseDetail(string url, object pars, Method type)
        {
            var request = new RestRequest(type);
            if (pars != null)
                request.AddObject(pars);
            var client = new RestClient(this.ApiBaseUrl + url);
            IRestResponse<R<T>> reval = client.Execute<R<T>>(request);
            if (reval.ErrorException != null)
                throw new UserFriendlyException("请求出错");
            if (!reval.Data.Success)
                throw new UserFriendlyException(reval.Data.Error == null ? "请求出错" : reval.Data.Error.Message);

            return reval.Data.Result;
        }

        private List<T> ParseList(string url, object pars, Method type)
        {
            var request = new RestRequest(type);
            if (pars != null)
                request.AddObject(pars);
            var client = new RestClient(this.ApiBaseUrl + url);
            IRestResponse<R<List<T>>> reval = client.Execute<R<List<T>>>(request);
            if (reval.ErrorException != null)
                throw new UserFriendlyException("请求出错");
            if (!reval.Data.Success)
                throw new UserFriendlyException(reval.Data.Error == null ? "请求出错" : reval.Data.Error.Message);

            return reval.Data.Result;
        }

        private PagedList<T> ParsePagedList(string url, PageDto pager, Method type, object pars = null)
        {
            var request = new RestRequest(type);
            if (pager != null)
                request.AddObject(pager);
            if (pars != null)
                request.AddObject(pars);
            var client = new RestClient(this.ApiBaseUrl + url);
            IRestResponse<R<PagedList<T>>> reval = client.Execute<R<PagedList<T>>>(request);
            if (reval.ErrorException != null)
                throw new UserFriendlyException("请求出错");
            if (!reval.Data.Success)
                throw new UserFriendlyException(reval.Data.Error == null ? "请求出错" : reval.Data.Error.Message);

            return reval.Data.Result;
        }
    }
}
